package battleGame;


import java.awt.Toolkit;

import battleGame.Army.WarriorCommand;
import battleGame.Warrior.WarriorState;

public class Archer extends Warrior 
{
		
	public Archer(int r, int c, int type, Army myArmy){
		
		super();
		
		hp = 30; //fixed hp for now
//		row = r;
//		col = c;
		
		position = new Vector2( c * ( Renderer.WINDOW_SIZE_X / 26 ), r * ( Renderer.WINDOW_SIZE_Y / 18 ) );
		loadImages( type );
		currentAction = WarriorAction.Action.WAIT;
		state = WarriorState.waiting;
		team = type;
		this.spaceRadius = 15;
		this.sightDistance = Renderer.TILE_SIZE * 5;
		this.attackRadius = 50;
		this.ejercito = myArmy;
		speed = 25;
		attackDamage = 6;
	}
	
	public void loadImages(int type)
	{
		int i = 0;
		switch(type){	
		//load standImages
		case 1:
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//right.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//downright.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//down.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//downleft.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//left.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//upleft.png"));
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//up.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//upright.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//death.png"));
			
		break;
		
		case 2:
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//right.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//downright.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//down.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//downleft.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//left.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//upleft.png"));
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//up.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//upright.png"));	
			standImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//death.png"));
			
		break;	
		
		}
		
		i = 0;
		switch(type){	
		//load standImages
		case 1:
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkright.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkdownright.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkdown.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkdownleft.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkleft.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkupleft.png"));
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkup.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//walkupright.png"));	
			
			
		break;
		
		case 2:
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkright.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkdownright.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkdown.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkdownleft.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkleft.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkupleft.png"));
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkup.png"));	
			walkImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//walkupright.png"));	
			
			
		break;	
		
		}
		 i=0;
		switch(type){	
		//load standImages
		case 1:
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackright.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackdownright.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackdown.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackdownleft.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackleft.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackupleft.png"));
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackup.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer//attackupright.png"));	
			
			
		break;
		
		case 2:
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackright.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackdownright.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackdown.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackdownleft.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackleft.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackupleft.png"));
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackup.png"));	
			attackImage[ i++ ]=(Toolkit.getDefaultToolkit().getImage("img//archer2//attackupright.png"));	
			
			
		break;	
		
		}
		icon = standImage[0];
	
	}
	
	public void order( Army.WarriorCommand command, Vector2 targetPosition )
	{
		if( commandTargetPosition != null )
		{
			if(World.GetInstance().GetTile(commandTargetPosition.getGridCol(), commandTargetPosition.getGridRow()) != null)
				World.GetInstance().GetTile(commandTargetPosition.getGridCol(), commandTargetPosition.getGridRow()).label = "";
		}
		commandTargetPosition = targetPosition;
		//enum WarriorCommand{ searchFlag, attack, flyAway, move, standBy, MAX };
		switch( command )
		{
			case defend:
			case attack:
			case move:
				actualCommand = command;
				findNewPathTo( targetPosition );
				
				if( listPath != null && listPath.size() > 0 )
				{
					this.processLookAtBasedOnPath();
	
					World.GetInstance().GetTile(targetPosition.getGridCol(), targetPosition.getGridRow()).label = "" + team;
				}
				break;
				
			case searchFlag:
				Vector2 target = getRandomPositionAtRadius( Renderer.TILE_SIZE * 8 );
				findNewPathTo( target );
				processLookAtBasedOnPath();
				Tile tile = World.GetInstance().GetTile( target.getGridCol(), target.getGridRow());
//				if( tile != null )
//					tile.label = "" + team;
				actualCommand = Army.WarriorCommand.searchFlag;
				break;
		}
	}
	
   public void animate(){
	   
	   switch( currentAction )
	   {
	   case WAIT:
		   //change image here
		   
		   break;
	   case MOVE:		   
		   //move()
		   
	   		break;
	   }
	   
   }
   
   public void move()
   {
	  
	   
   }


	@Override
	public WarriorAction actionTurn() 
	{
		if( state == WarriorState.performingAction )
		{
			if( attackTime > 0 )
			{
				attackTime -= Time.getDeltaTime();
				this.currentAction = WarriorAction.Action.ATTACKARROW;
				if( attackTime <= 0 )
				{
					this.currentAction = WarriorAction.Action.WAIT;
					this.waitTime = Constant.waitAttackTime;
				}
				return WarriorActionFactory.waiting();
			}
			else if( waitTime > 0 )
			{
				waitTime -= Time.getDeltaTime();
				return WarriorActionFactory.waiting();
			}
			else switch( actualCommand )
			{
				case move:	
					return performMoveCommand();
				case searchFlag:
					return performSearchFlagCommand();
				case defend:
					return performDefendCommand();
				case attack:
					return performAttackCommand();
					
					
			}
		}
			
		//lookAt = new Vector2( -1, 0 );
		// TODO Auto-generated method stub
		return WarriorActionFactory.rotate( this, 0.0001 );
	}
	
	void processLookAtBasedOnPath()
	{
		if( listPath != null && listPath.size() > 0 && pathIndex < listPath.size() )
		{
			Tile nextTile = (Tile)listPath.get( pathIndex );
			int[] coords = World.GetInstance().getCoordsFromID(nextTile.id);
			Vector2 nextTilePosition = Vector2.GetVector2FromColRow( coords[ 1 ], coords[ 0 ] );
			lookAt = Vector2.minus(nextTilePosition, position);
			lookAt.normalize();
		}
	}
	
	void findNewPathTo( Vector2 targetPosition )
	{
		listPath = AStarSearch.performSearch( position.getGridCol(), 
				  position.getGridRow(),	 
				  targetPosition.getGridCol(), 
				  targetPosition.getGridRow() );
		pathIndex = 0;
		state = WarriorState.performingAction;
	}
	
	Vector2 getRandomPositionAtRadius( double radius )
	{
		Vector2 miReturn;
		do{
			Vector2 offset = new Vector2( 1, 0 );
			offset.rotate( Utils.rand.nextDouble() * 2 * Math.PI );
			offset = Vector2.mul(offset, Utils.rand.nextDouble() * radius / 2 + radius / 2 );
			miReturn = Vector2.suma(position, offset);
		}while( miReturn.x < 0 || miReturn.x >= Renderer.WINDOW_SIZE_X || miReturn.y < 0 || miReturn.y >= Renderer.WINDOW_SIZE_Y );
		return miReturn;
	}
	
	WarriorAction performMoveCommand()
	{
		if( listPath == null || pathIndex >= listPath.size() )
		{
			actualCommand = Army.WarriorCommand.none;
			state = WarriorState.waiting;
			currentAction = WarriorAction.Action.WAIT;
			World.GetInstance().GetTile(position.getGridCol(), position.getGridRow()).label = "";
			return WarriorActionFactory.waiting();
		}
		else
		{
			//He llegado al siguiente nodo?
			Tile nodoActual = World.GetInstance().GetTile( position.getGridCol(), position.getGridRow() );
			if( nodoActual != null && listPath.get( pathIndex ).id == nodoActual.id )
			{
				//El personaje debe de rotar para seguir su camino
				pathIndex++;
				if( pathIndex < listPath.size() )
				{
					processLookAtBasedOnPath();
					
					currentAction = WarriorAction.Action.MOVE;
					return WarriorActionFactory.move(this, position);
					//return WarriorActionFactory.rotate( this, -1 * Vector2.GetAngleBetween(lookAt, Vector2.minus( nextTilePosition, position ) ) );
				}
			}
			else
			{
				processLookAtBasedOnPath();

				//Caminemos a nuestra direccion;
				Vector2 nuevaPosicion;
				Vector2 deltaVector = Vector2.mul( lookAt, speed * Time.getDeltaTime() );
				//System.out.print( "DeltaTime: " + Time.getDeltaTime() + " - Desplazamiento: " + deltaVector.x + ", " + deltaVector.y + "\n" );
				nuevaPosicion = Vector2.suma(position, deltaVector);
				currentAction = WarriorAction.Action.MOVE;
				return WarriorActionFactory.move(this, nuevaPosicion);
			}
		}
		currentAction = WarriorAction.Action.WAIT;
		return WarriorActionFactory.rotate( this, 0.0001 );		
	}
	
	WarriorAction performSearchFlagCommand()
	{
		if( listPath == null || pathIndex >= listPath.size() )
		{
			World.GetInstance().GetTile(position.getGridCol(), position.getGridRow()).label = "";
			Vector2 target = getRandomPositionAtRadius( Renderer.TILE_SIZE * 8 );
			commandTargetPosition = target;
			findNewPathTo( target );
			Tile tile = World.GetInstance().GetTile( target.getGridCol(), target.getGridRow());
//			if( tile != null )
//				tile.label = "" + team;
		}
		
		if( listPath == null || pathIndex >= listPath.size() )
		{
			currentAction = WarriorAction.Action.WAIT;
			return WarriorActionFactory.waiting();						
		}
			

		//He llegado al siguiente nodo?
		Tile nodoActual = World.GetInstance().GetTile( position.getGridCol(), position.getGridRow() );
		if( nodoActual != null && listPath.get( pathIndex ).id == nodoActual.id )
		{
			//El personaje debe de rotar para seguir su camino
			pathIndex++;
		}
		if( pathIndex < listPath.size() )
		{
			processLookAtBasedOnPath();

			//Caminemos a nuestra direccion;
			Vector2 nuevaPosicion;
			Vector2 deltaVector = Vector2.mul( lookAt, speed * Time.getDeltaTime() );
			//System.out.print( "DeltaTime: " + Time.getDeltaTime() + " - Desplazamiento: " + deltaVector.x + ", " + deltaVector.y + "\n" );
			nuevaPosicion = Vector2.suma(position, deltaVector);
			currentAction = WarriorAction.Action.MOVE;
			return WarriorActionFactory.move(this, nuevaPosicion);
		}		
		currentAction = WarriorAction.Action.WAIT;
		return WarriorActionFactory.rotate( this, 0.0001 );		
	}
	
	WarriorAction performAttackCommand()
	{
		Warrior enemy;
		WarriorAction warriorAction = null;
		if( ( enemy = isEnemyInAttackRange() ) != null )
		{
			lookAt = Vector2.minus( enemy.position, this.position ).normalize();
			currentAction = WarriorAction.Action.ATTACKARROW;
			attackTime = Constant.arrowAttackTime;
			return WarriorActionFactory.attackArrow( this, enemy );
		}
		else if( (enemy = isEnemyOnSight() ) != null )
		{
			lookAt = Vector2.minus( enemy.position, this.position ).normalize();
			Vector2 nuevaPosicion;
			Vector2 deltaVector = Vector2.mul( lookAt, speed * Time.getDeltaTime() );
			//System.out.print( "DeltaTime: " + Time.getDeltaTime() + " - Desplazamiento: " + deltaVector.x + ", " + deltaVector.y + "\n" );
			nuevaPosicion = Vector2.suma(position, deltaVector);
			currentAction = WarriorAction.Action.MOVE;
			warriorAction =  WarriorActionFactory.move(this, nuevaPosicion);
		}
		else
		{
			currentAction = WarriorAction.Action.MOVE;
			warriorAction = performMoveCommand();
		}
		actualCommand = Army.WarriorCommand.attack;
		return warriorAction;		
	}
	
	WarriorAction performDefendCommand()
	{
		Warrior enemy;
		WarriorAction warriorAction = null;
		if( ( enemy = isEnemyInAttackRange() ) != null )
		{
			lookAt = Vector2.minus( enemy.position, this.position ).normalize();
			currentAction = WarriorAction.Action.ATTACKARROW;
			attackTime = Constant.arrowAttackTime;
			return WarriorActionFactory.attackArrow( this, enemy );
		}
		else if( (enemy = isEnemyOnSight() ) != null && Vector2.minus( enemy.position, commandTargetPosition).magnitude() < Constant.defendingFlagDistance )
		{
			lookAt = Vector2.minus( commandTargetPosition, this.position ).normalize();
			Vector2 nuevaPosicion;
			Vector2 deltaVector = Vector2.mul( lookAt, speed * Time.getDeltaTime() );
			//System.out.print( "DeltaTime: " + Time.getDeltaTime() + " - Desplazamiento: " + deltaVector.x + ", " + deltaVector.y + "\n" );
			nuevaPosicion = Vector2.suma(position, deltaVector);
			currentAction = WarriorAction.Action.MOVE;
			warriorAction =  WarriorActionFactory.move(this, nuevaPosicion);
		}
		else
		{
			currentAction = WarriorAction.Action.MOVE;
			warriorAction =  performMoveCommand();
		}
		actualCommand = Army.WarriorCommand.defend;
		return warriorAction;
	}
	
	Warrior isEnemyInAttackRange()
	{
		for( int i = 0; i < actualSight.size(); i++ )
		{
			Warrior warrior;
			if( actualSight.get( i ) instanceof Warrior )
			{
				warrior = (Warrior)actualSight.get( i );
				if( warrior.team != this.team && Utils.fIsWarriorInAttackRange( this, warrior ) )
					return warrior;
			}
		}
		return null;
		
	}	

	Warrior isEnemyOnSight()
	{
		for( int i = 0; i < actualSight.size(); i++ )
		{
			Warrior warrior;
			if( actualSight.get( i ) instanceof Warrior )
			{
				warrior = (Warrior)actualSight.get( i );
				if( warrior.team != this.team )
					return warrior;
			}
		}
		return null;
		
	}	
}
